package cgl.narada.service.security.kmc;

import java.io.IOException;
import java.io.Serializable;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.cert.Certificate;

import org.apache.log4j.Logger;

import cgl.narada.service.ServiceException;
import cgl.narada.service.security.impl.EntityOperationsImpl;
import cgl.narada.util.ObjectMarshaller;

/**
 * Encapsulates the security token, the signer's certificate(KMC) and the signed signature
 * <br>
 * Created on Sep 9, 2005
 * @author Harshawardhan Gadgil (hgadgil@grids.ucs.indiana.edu)
 */
public class SignedSecurityToken implements Serializable {

    static Logger log = Logger.getLogger("SignedSecurityToken");
    
    private SecurityToken securityToken;

    private Certificate kmcCertificate;

    private byte[] signedDigest;

    // Disable this Constructor
    private SignedSecurityToken() {
    }

    public SignedSecurityToken(SecurityToken token, Certificate cert) {
        securityToken = token;
        kmcCertificate = cert;
        signedDigest = null;
    }

    public boolean generateSignedDigest(PrivateKey privKey) {
        try {
            EntityOperationsImpl entityOperations = new EntityOperationsImpl();
            signedDigest = entityOperations.signPayload(securityToken
                    .getBytes(), privKey);
        } catch (ServiceException e) {
            log.error("Exception when generating Signature: ", e);
            log.info("Process Abandoned");
            return false;
        }

        return true;
    }

    public boolean verify() {
        return verify(kmcCertificate.getPublicKey());
    }

    public boolean verify(PublicKey pubKey) {
        try {
            EntityOperationsImpl entityOperations = new EntityOperationsImpl();
            return entityOperations.validateSignature(signedDigest,
                    securityToken.getBytes(), pubKey);

        } catch (ServiceException e) {
            log.error("", e);
            return false;
        }
    }

    /**
     * Marshalls the object into an array of bytes.
     * 
     * @return an array of bytes representing the marshaller object, null if
     *         error occurs
     */
    public byte[] getBytes() {

        if (signedDigest == null)
            return null;

        try {
            return ObjectMarshaller.marshall(this);
        } catch (IOException e) {
            log.error("", e);
            return null;
        }
    }

    /**
     * Unmarshalls the bytes as a SignedSecurityToken object
     * 
     * @param objectBytes
     * @return SignedSecurityToken if successful, null if error occurs
     */
    public static SignedSecurityToken createObjectFromBytes(byte[] objectBytes) {
        try {
            return (SignedSecurityToken) ObjectMarshaller
                    .unmarshall(objectBytes);
        } catch (IOException e) {
            log.error("", e);
        } catch (ClassNotFoundException e) {
            log.error("", e);
        }
        return null;
    }

    /**
     * @return Returns the kmcCertificate.
     */
    public Certificate getKmcCertificate() {
        return kmcCertificate;
    }

    /**
     * @return Returns the securityToken.
     */
    public SecurityToken getSecurityToken() {
        return securityToken;
    }
}
